package com.yzpass.api.security;

import com.yzpass.api.security.annotation.*;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.lang.reflect.Method;
import java.util.Set;

@Aspect
@Component
public class PermissionAspect {
    @Before("@annotation(com.yzpass.api.security.annotation.RequirePermission)")
    public void checkRequirePermission(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequirePermission requirePermission = method.getAnnotation(RequirePermission.class);
        String permission =  requirePermission.value() + ":" + requirePermission.level().getTitle() ;
        checkPermission(permission);
    }
    @Before("@annotation(com.yzpass.api.security.annotation.RequireRead)")
    public void checkRequireRead(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequireRead requireRead = method.getAnnotation(RequireRead.class);
        String permission =  requireRead.value() + ":" + PermissionLevel.READ.getTitle();
        checkPermission(permission);
    }
    @Before("@annotation(com.yzpass.api.security.annotation.RequireEdit)")
    public void checkRequireEdit(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequireEdit requireRead = method.getAnnotation(RequireEdit.class);
        String permission =  requireRead.value()  + ":" + PermissionLevel.EDIT.getTitle();
        checkPermission(permission);
    }

    @Before("@annotation(com.yzpass.api.security.annotation.RequireFullControl)")
    public void checkRequireFullControl(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequireFullControl requireRead = method.getAnnotation(RequireFullControl.class);
        String permission =  requireRead.value()  + ":" + PermissionLevel.FULLCONTROL.getTitle();
        checkPermission(permission);
    }

    private void checkPermission(String permission) {
        var attr = RequestContextHolder.getRequestAttributes();
        if(attr!=null){
            var permissions =  attr.getAttribute("permissions", RequestAttributes.SCOPE_REQUEST);
            if (permissions != null) {
                if(permissions instanceof Set set){
                    if(set.contains(permission)){
                        return;
                    }
                }
            }
        }
        throw new NoPermissionException("您没有权限访问当前接口，需要权限:" + permission + "，请联系管理员");
    }

    @Before("@annotation(com.yzpass.api.security.annotation.RequireAnyPermission)")
    public void checkRequireAnyPermission(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequireAnyPermission anyPermission = method.getAnnotation(RequireAnyPermission.class);
        Set<String> permissionSet = getPermissionSet();
        boolean match = false;
        if(anyPermission.value()!=null){
            for(String str:anyPermission.value()){
                String key = str + ":" + anyPermission.level().getTitle();
                if(permissionSet.contains(key)){
                    match = true;
                    break;
                }
            }
        }
        if(anyPermission.permissions()!=null){
            for(RequirePermission permission: anyPermission.permissions()){
                String key = permission.value() + ":" + permission.level().getTitle();
                if(permissionSet.contains(key)){
                    match = true;
                    break;
                }
            }
        }
        if(!match){
            throw new NoPermissionException("您没有权限访问当前接口，请联系管理员");
        }
    }
    @Before("@annotation(com.yzpass.api.security.annotation.RequireAllPermission)")
    public void checkRequireAllPermission(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequireAllPermission allPermission = method.getAnnotation(RequireAllPermission.class);
        Set<String> permissionSet = getPermissionSet();
        boolean match = true;
        if(allPermission.value()!=null){
            for(String str:allPermission.value()){
                String key = str + ":" + allPermission.level().getTitle();
                if(permissionSet.contains(key)){
                    match = false;
                    break;
                }
            }
        }
        if(allPermission.permissions()!=null){
            for(RequirePermission permission: allPermission.permissions()){
                String key = permission.value() + ":" + permission.level().getTitle();
                if(permissionSet.contains(key)){
                    match = false;
                    break;
                }
            }
        }
        if(!match){
            throw new NoPermissionException("您没有权限访问当前接口，请联系管理员");
        }
    }
    private Set<String> getPermissionSet(){
        var attr = RequestContextHolder.getRequestAttributes();
        if(attr!=null){
            var permissions =  attr.getAttribute("permissions", RequestAttributes.SCOPE_REQUEST);
            if (permissions != null) {
                if(permissions instanceof Set set){
                    return set;
                }
            }
        }
        return Set.of();
    }
}